/*
 * Copyright 2018 The JA-SIG Collaborative. All rights reserved.
 * distributed with thi file and available online at
 */
package com.lap.scp.admin.config;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Lazy;

import com.lap.scd.commons.result.Resp;
import com.lap.scp.admin.ao.ResourcesAO;
import com.lap.scp.admin.ao.UserAO;
import com.lap.scp.admin.domain.UserDO;
import com.lap.scp.admin.utils.ErpEnums.Yn;

/**
 * <pre>
 * 授权认证类，这里重写了两个方法，
 * 1、标签资源授权；
 * 2、登录认证
 * </pre>
 * 
 * @author 劳水生 Exp
 * @Date 2018年1月23日 下午4:00:24
 * @since 1.0
 */
public class AdminAuthRealm extends AuthorizingRealm {
	/**
	 * 这里增加 lazy，防止对这两个类的缓存不生效
	 */
	@Lazy
	@Resource
	private UserAO userAO;
	/**
	 * 这里增加 lazy，防止对这两个类的缓存不生效
	 */
	@Lazy
	@Resource
	private ResourcesAO resourcesAO;

	/**
	 * <pre>
	 * 资源授权,包括页面标签、拦截器的权限认证.
	 * 
	 * </pre>
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pcn) {
		UserDO userDO = (UserDO) pcn.fromRealm(getName()).iterator().next();
		List<String> list = resourcesAO.queryUrlByUserId(userDO.getId());

		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		Set<String> permissions = new HashSet<>();
		if (list != null) {
			for (String str : list) {
				if (StringUtils.isNotBlank(str)) {
					permissions.add(str);
				}
			}
		}
		info.addStringPermissions(permissions);
		return info;
	}

	/**
	 * <pre>
	 * 登录认证
	 * </pre>
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String username = (String) token.getPrincipal();
		Resp<UserDO> resp = userAO.queryByUsername(username);
		if (!resp.isSuccess()) {
			return null;
		} else {
			UserDO userDO = resp.getData();
			if (Yn.No.getValue() == userDO.getStatus()) {
				throw new LockedAccountException();
			} else {
				this.clearLogin(username);
				return new SimpleAuthenticationInfo(userDO, userDO.getPasswd(), getName());
			}
		}
	}

	/**
	 * <pre>
	 * 提出当前已经登录的帐号，防止一个帐号多个地方登录
	 * 
	 * 	DefaultSecurityManager securityManager = (DefaultSecurityManager) SecurityUtils.getSecurityManager();
		DefaultWebSessionManager sessionManager = (DefaultWebSessionManager) securityManager.getSessionManager();
	 * </pre>
	 * 
	 * @param username
	 */
	private void clearLogin(String username) {
		DefaultSecurityManager securityManager = (DefaultSecurityManager) SecurityUtils.getSecurityManager();
		DefaultWebSessionManager sessionManager = (DefaultWebSessionManager) securityManager.getSessionManager();
		Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();
		for (Session session : sessions) {
			Object sessionObj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
			if (sessionObj != null) {
				SimplePrincipalCollection spc = (SimplePrincipalCollection) sessionObj;
				UserDO sessionUser = (UserDO) spc.getPrimaryPrincipal();
				if (sessionUser != null && username.equals(sessionUser.getUsername())) {
					sessionManager.getSessionDAO().delete(session);
				}
			}
		}
	}

}
